#!/usr/bin/env python 
# This code is Public Domain. 
"""Python-Ogre Basic Tutorial 01: The SceneNode, Entity, and SceneManager constructs.""" 

import ogre.renderer.OGRE as ogre 
import ogre.io.OIS as OIS
import SampleFramework as sf 

import maultasche as mt

##from pydoc import help
##help(OIS._ois_.Axis)
##exit()

res = (800, 600)

class TutorialFrameListener(sf.FrameListener):
    """A FrameListener class that handles basic user input."""
        
    def __init__(self, renderWindow, camera, sceneManager, objManager):
        # Subclass any Python-Ogre class and you must call its constructor.
        sf.FrameListener.__init__(self, renderWindow, camera)
        
        # Key and mouse state tracking.
        self.toggle = 0
        self.mouseDown = False

        # Populate the camera and scene manager containers.
        self.camNode = camera.getParentSceneNode()
        self.sceneManager = sceneManager
        self.objMgr = objManager

        # Set the rotation and movement speed.
        self.rotate = 0.13
        self.move = 50
        self.zoomspeed = 40
        self.zoomfactor = 1.0
        
        self.selected = []
        
        
        # Create RaySceneQuery
        self.raySceneQuery = self.sceneManager.createRayQuery( ogre.Ray( ) );

    def frameStarted(self, frameEvent):
        # If the render window has been closed, end the program.
        if(self.renderWindow.isClosed()):
            return False

        # Capture and update each input device.
        self.Keyboard.capture()
        self.Mouse.capture()
        
        # Get the current mouse state.
        currMouse = self.Mouse.getMouseState()

        # Update the toggle timer.
        if self.toggle >= 0:
            self.toggle -= frameEvent.timeSinceLastFrame
        
        # Swap the camera's viewpoint with the keys 1 or 2.
        if self.toggle < 0 and self.Keyboard.isKeyDown(OIS.KC_1):
            for unit in self.selected:
                unit.node.showBoundingBox(False)
            
            self.selected = [self.objMgr.entities[0]]
            
            for unit in self.selected:
                unit.node.showBoundingBox(True)
            
        elif self.toggle < 0 and self.Keyboard.isKeyDown(OIS.KC_2):
            for unit in self.selected:
                unit.node.showBoundingBox(False)
            
            self.selected = [self.objMgr.entities[1]]
            
            for unit in self.selected:
                unit.node.showBoundingBox(True)
            
        elif self.toggle < 0 and self.Keyboard.isKeyDown(OIS.KC_3):
            for unit in self.selected:
                unit.node.showBoundingBox(False)
            
            self.selected = [self.objMgr.entities[2]]
            
            for unit in self.selected:
                unit.node.showBoundingBox(True)
                        
        # Move the camera using keyboard input.
        transVector = ogre.Vector3(0, 0, 0)
        # Move Forward.
        if self.Keyboard.isKeyDown(OIS.KC_W):
           transVector.y += self.move
        # Move Backward.
        if self.Keyboard.isKeyDown(OIS.KC_S):
            transVector.y -= self.move
        # Strafe Left.
        if self.Keyboard.isKeyDown(OIS.KC_A):
            transVector.x -= self.move
        # Strafe Right.
        if self.Keyboard.isKeyDown(OIS.KC_D):
            transVector.x += self.move
            
        if self.Keyboard.isKeyDown(OIS.KC_Q):
            transVector.z -= self.zoomspeed
            self.zoomfactor -= 0.1
        if self.Keyboard.isKeyDown(OIS.KC_Z):
            transVector.z += self.zoomspeed
            self.zoomfactor += 0.1
        
        if currMouse.X.abs > res[0] - 24:
            transVector.x += self.move
        elif currMouse.X.abs < 24:
            transVector.x -= self.move
        
        if currMouse.Y.abs > res[1] - 24:
            transVector.y -= self.move
        elif currMouse.Y.abs < 24:
            transVector.y += self.move
        
        # Translate the camera based on time.
        self.camNode.translate(self.camNode.orientation
                               * transVector
                               * frameEvent.timeSinceLastFrame)
        
        # Use the Left mouse button to turn Light1 on and off.         
        if currMouse.buttonDown(OIS.MB_Left) and not self.mouseDown:
            # Setup the scene query
            camPos = self.camera.getPosition()
            cameraRay = ogre.Ray(ogre.Vector3(camPos.x, camPos.y, camPos.z), ogre.Vector3.NEGATIVE_UNIT_Y )
            self.raySceneQuery.setRay( cameraRay )

            # Perform the scene query
            result = self.raySceneQuery.execute()

            for obj in result:
                # pick out entities
                if isinstance(obj.movable, ogre.Entity):
                    picked = obj.movable
                    
                    #figure out which object this entity goes with
                    print picked.name
                if obj.worldFragment is not None:
                    print "worldFrag"
            # Get the results, set the camera height
            #if ( itr != result.end() && itr->worldFragment )
            #{
            #    Real terrainHeight = itr->worldFragment->singleIntersection.y;
            #    if ((terrainHeight + 10.0f) > camPos.y)
            #        mCamera->setPosition( camPos.x, terrainHeight + 10.0f, camPos.z );
            #}                   
            
              
        # Update the mouseDown boolean.            
        self.mouseDown = currMouse.buttonDown(OIS.MB_Left)
        
        # Use the Left mouse button to turn Light1 on and off.         
        if currMouse.buttonDown(OIS.MB_Right):
            if self.selected != []:
                # Setup the scene query
                camPos = self.camera.getPosition()
                cameraRay = ogre.Ray(ogre.Vector3(camPos.x, camPos.y, camPos.z), ogre.Vector3.NEGATIVE_UNIT_Y )
                
                # make a plane for the playing field
                plane = ogre.Plane( ogre.Vector3(1,0,0), ogre.Vector3(0,0,0) )
                
                # see if the camera ray intersects it
                info = cameraRay.intersects(plane)

                # we get a pair: a bool and a real number
                if info.first is True:
                    intersection = cameraRay.getPoint(info.second)
                    self.selected[0].goTo(mt.Point(intersection.x, intersection.y))
                else:
                    print "move command ray doesn't intersect! damnit!"
            
        # If the escape key is pressed end the program.
        return not self.Keyboard.isKeyDown(OIS.KC_ESCAPE)
     
        # now do game logic stuff
        # <FIXME> move this to a different frame listener
        self.objMgr.update(frameEvent.timeSinceLastFrame)
        
        # </FIXME>

class TutorialApplication(sf.Application): 
    """Application class.""" 
    
    def _createScene(self):
        self.objManager = mt.UnitManager(self.sceneManager)
        mObjMgr = self.objManager
        mSceneMgr = self.sceneManager
        
        # Create a scene with terrain, sky and fog.
        #mSceneMgr.setWorldGeometry("terrain.cfg")
          
        # Setup the ambient light. 
        mSceneMgr.ambientLight = (0.4, 0.4, 0.4) 
        
        # Setup a primary light source
        
        # Create a light
        l = mSceneMgr.createLight("MainLight")
        # Accept default settings: point light, white diffuse, just set position
        # NB I could attach the light to a SceneNode if I wanted it to move automatically with
        #  other objects, but I don't
        l.setPosition(-100,100,100)
        l.type = ogre.Light.LT_POINT
        #l.setAttenuation(1000, 0.5, 0.5, 0.5) # range, constant, linear, quadratic
        node = mSceneMgr.rootSceneNode.createChildSceneNode('CamNode')
        node.attachObject(self.camera)
        node.attachObject(l)
        node.translate(0, 0, 40)
        
        keep = mSceneMgr.createEntity('keep', 'keep.mesh')
        keep.setMaterialName("Maultasche/PseudoFlat") 
        node4 = mSceneMgr.rootSceneNode.createChildSceneNode('keepNode')
        node4.attachObject(keep)
        node4.pitch(ogre.Degree(90))
        node4.translate(-10,0,0)
        
        ent4 = mSceneMgr.createEntity('platform', 'platform.mesh')
        ent4.setMaterialName("Maultasche/PseudoFlat") 
        node4.attachObject(ent4)

        sub = keep.getSubEntity(0)
        mMaterial = sub.getMaterial().clone("Teams/" + "Independents")
        #clone the material on a name-by-name basis
        
        # set team color
        mMaterial.setAmbient(0.6, 0.6, 0.6)
        mMaterial.setDiffuse(0.6, 0.6, 0.6, 1.0)
        mMaterial.setSpecular(1.0, 1.0, 1.0, 1.0)        
        
        mMaterial = sub.getMaterial().clone("Teams/" + "Red")
        
        # set team color
        mMaterial.setAmbient(1.0, 0.2, 0.2)
        mMaterial.setDiffuse(1.0, 0.2, 0.2, 1.0)
        mMaterial.setSpecular(1.0, 1.0, 1.0, 1.0)

        mMaterial = sub.getMaterial().clone("Teams/" + "Green")
        
        # set team color
        mMaterial.setAmbient(0.2, 1.0, 0.2)
        mMaterial.setDiffuse(0.2, 1.0, 0.2, 1.0)
        mMaterial.setSpecular(1.0, 1.0, 1.0, 1.0)
        
        mMaterial = sub.getMaterial().clone("Teams/" + "Blue")
        
        # set team color
        mMaterial.setAmbient(0.2, 0.2, 1.0)
        mMaterial.setDiffuse(0.2, 0.2, 1.0, 1.0)
        mMaterial.setSpecular(1.0, 1.0, 1.0, 1.0)


        footie = mObjMgr.createUnit("footman", "Red")
        
        skirm = mObjMgr.createUnit("skirmisher", "Green")
        skirm.setPos(1, 0)
        
        run = mObjMgr.createUnit("runner", "Blue")
        run.setPos(2, 0)
        
        
        # now to set up more game-logicky stuff
        #mycompany = Company(footman, footman, footman)
        
    
    def _createCamera(self):
        self.camera =  self.sceneManager.createCamera('PlayerCam')
        self.camera.position = (0, 0, 0)
        self.camera.lookAt((0, 0, 0))
        self.camera.nearClipDistance = 1

    def _createViewports(self):
        viewport = self.renderWindow.addViewport(self.camera)
        viewport.backGroundColor = (0, 0, 0)
        self.camera.aspectRatio = float(viewport.actualWidth) / float(viewport.actualHeight)
    
    def _createFrameListener(self):
        self.frameListener = TutorialFrameListener(self.renderWindow,
                                                   self.camera,
                                                   self.sceneManager,
                                                   self.objManager)
        self.root.addFrameListener(self.frameListener)
        self.frameListener.showDebugOverlay(True)


if __name__ == '__main__': 
    ta = TutorialApplication() 
    ta.go()
